<template>
  <div>
    <el-upload :action="uploadFileUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
               :on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" style="display: none"
               :data="data" ref="upload" v-if="this.type === 'url'">
    </el-upload>
    <div class="editor" ref="editor" :style="styles" style="overflow-y: scroll;max-height: 500px;"></div>
  </div>
</template>

<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { getAccessToken } from "@/utils/auth";
import Vue from "vue";
import VueQuillEditor from "vue-quill-editor";


/*

const codeBlock = Quill.import('formats/code-block') // 引入这个后会把样式写在style上
Quill.register(codeBlock, true)
*/


// 注册自定义处理函数
Quill.register('formats/indent', Quill.import('formats/indent'), true);

// 设置字体大小
const sizeList = ['10px', false, '18px', '32px']//把哪个参数改为false，刚参数则为默认值
const size = Quill.import('attributors/style/size') // 引入这个后会把样式写在style上
size.whitelist = sizeList
Quill.register(size, true)
const font = Quill.import('attributors/style/font') // 引入这个后会把样式写在style上
const fonts = [
  'SimSun',
  'SimHei',
  'Microsoft-YaHei',
  'KaiTi',
  'FangSong'
]
font.whitelist = fonts // 将字体加入到白名单
Quill.register(font, true)
let Align = Quill.import('attributors/style/align')
Quill.register(Align, true)

let Direction = Quill.import('attributors/style/direction')

Quill.register(Direction, true)
Vue.use(VueQuillEditor);


export default {
  name: "Editor",
  props: {
    /* 编辑器的内容 */
    value: {
      type: String,
      default: "",
    },
    /* 高度 */
    height: {
      type: Number,
      default: null,
    },
    /* 最小高度 */
    minHeight: {
      type: Number,
      default: null,
    },
    /* 只读 */
    readOnly: {
      type: Boolean,
      default: false,
    },
    // 上传文件大小限制(MB)
    fileSize: {
      type: Number,
      default: 5,
    },
    /* 类型（base64格式、url格式） */
    type: {
      type: String,
      default: "url",
    }
  },
  data() {
    return {
      data: {path: 'system/editor'},
      indentValue: 0,
      uploadFileUrl: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址
      headers: {Authorization: "Bearer " + getAccessToken()}, // 设置上传的请求头部
      Quill: null,
      currentValue: "",
      options: {
        theme: "snow",
        bounds: document.body,
        debug: "warn",
        modules: {
          // 工具栏配置
          toolbar: [
            ["bold", "italic", "underline", "strike"],       // 加粗 斜体 下划线 删除线
            ["blockquote", "code-block"],                    // 引用  代码块
            [{list: "ordered"}, {list: "bullet"}],       // 有序、无序列表
            [{indent: "-1"}, {indent: "+1"}],            // 缩进
            [{size: sizeList}],                            // 字体大小
            [{header: [1, 2, 3, 4, 5, 6, false]}],         // 标题
            [{color: []}, {background: []}],             // 字体颜色、字体背景颜色
            [{align: []}],                                 // 对齐方式
            ["clean"],                                       // 清除文本格式
            ["link", "image", "video"],                      // 链接、图片、视频

          ],
        },
        placeholder: "请输入内容",
        readOnly: true,
      },
    };
  },
  computed: {
    styles() {
      let style = {};
      if (this.minHeight) {
        style.minHeight = `${this.minHeight}px`;
      }
      if (this.height) {
        style.height = `${this.height}px`;
      }
      return style;
    },
  },
  watch: {
    value: {
      handler(val) {
        if (val !== this.currentValue) {
          this.currentValue = val === null ? "" : val;
          if (this.Quill) {
            this.Quill.pasteHTML(this.currentValue);
          }
        }
      },
      immediate: true,
    },
  },
  mounted() {
    this.init();
  },
  beforeDestroy() {
    this.Quill = null;
  },
  methods: {
    removeAllInlineStyles(element) {
      // 移除当前元素的内联样式
      element.removeAttribute('style');
      // 递归遍历子元素并移除它们的内联样式
      let childNodes = element.childNodes;
      for (let i = 0; i < childNodes.length; i++) {
        let child = childNodes[i];
        if (child.nodeType === 1) { // 检查是否是元素节点
          this.removeAllInlineStyles(child); // 递归调用，移除子元素的内联样式
        }
      }
    }
    ,
    init() {
      const editor = this.$refs.editor;
      this.Quill = new Quill(editor, this.options);
      // 取消自动聚焦 start
      this.$nextTick(() => {
        this.Quill.blur();
        if (!this.readOnly) {
          this.Quill.enable();
        }
      });
      let _this = this;
      this.Quill.getModule('toolbar').addHandler('indent', function (value) {
        let quill = _this.Quill;
        //获取当前编辑器的选区
        let range = quill.getSelection(true);
        if (range) {
          let startIndex = range.index;
          let endIndex = range.index + range.length;
          let lines = [];
          for (let i = startIndex; i < endIndex; i++) {
            // 获取当前行的范围
            let currentLine = quill.getLine(i);
            // 如果当前行存在
            if (currentLine && !lines.includes(currentLine[0].domNode)) {
              // 添加 CSS 样式来实现首行缩进
              let textIndent = currentLine[0].domNode.style.textIndent;
              if (!textIndent) {
                textIndent = '0';
              }
              textIndent = parseInt(textIndent.replace('em', '')) + parseInt(value)
              currentLine[0].domNode.style = 'text-indent: ' + textIndent + 'em;'
              lines.push(currentLine[0].domNode)
            }
          }
        }
        let delta = {
          ops: [
            {retain: 0, insert: '', attributes: {}}
          ]
        };

        quill.emitter.emit('text-change', 'user', delta, delta, {});

      });
      this.Quill.getModule('toolbar').addHandler('clean', function (value) {
        let quill = _this.Quill;
        // 获取当前编辑器的选区
        let range = quill.getSelection(true);
        if (range) {
          let startIndex = range.index;
          let endIndex = range.index + range.length;
          let lines = [];
          for (let i = startIndex; i < endIndex; i++) {
            // 获取当前行的范围
            let currentLine = quill.getLine(i);
            // 如果当前行存在
            if (currentLine && !lines.includes(currentLine[0].domNode)) {
              _this.removeAllInlineStyles(currentLine[0].domNode)
              lines.push(currentLine[0].domNode)
            }
          }
        }
      });

      // 如果设置了上传地址则自定义图片上传事件
      if (this.type === 'url') {
        this.Quill.getModule("toolbar").addHandler("image", (value) => {
          if (value) {
            this.$refs.upload.$children[0].$refs.input.click();
          } else {
            _this.Quill.format("image", false);
          }
        });
      }
      this.Quill.pasteHTML(this.currentValue);
      this.Quill.on("text-change", (delta, oldDelta, source) => {
        const ops = delta.ops;
        ops.forEach((op) => {
          if (op.insert && op.insert.image && op.insert.image.includes('data:image')) {
            this.$message.error("请将复制的图片下载到本地进行上传");
            return;
          }
        });
        const text = this.Quill.getText();
        const quill = this.Quill;
        let innerHTML = this.$refs.editor.children[0].innerHTML;
        let html = null;
        if (innerHTML != null && innerHTML != '') {
          html = '<div style="line-height:1.8;letter-spacing:0.544px;font-size:16px">' + innerHTML + '</div>'
        }
        this.currentValue = html;
        this.$emit("input", html);
        this.$emit("on-change", {html, text, quill});
      });
      this.Quill.on("text-change", (delta, oldDelta, source) => {
        this.$emit("on-text-change", delta, oldDelta, source);
      });
      this.Quill.on("selection-change", (range, oldRange, source) => {
        this.$emit("on-selection-change", range, oldRange, source);
      });
      this.Quill.on("editor-change", (eventName, ...args) => {
        this.$emit("on-editor-change", eventName, ...args);
      });
    },
    // 上传前校检格式和大小
    handleBeforeUpload(file) {
      // 校检文件大小
      if (this.fileSize) {
        const isLt = file.size / 1024 / 1024 < this.fileSize;
        if (!isLt) {
          this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
          return false;
        }
      }
      return true;
    },
    handleUploadSuccess(res, file) {
      // 获取富文本组件实例
      let quill = this.Quill;
      // 如果上传成功
      // edit by 源码
      if (res.code === 200 || res.code === 0) {
        // 获取光标所在位置
        let length = quill.getSelection().index;
        // 插入图片  res.url为服务器返回的图片地址
        // edit by 源码
        quill.insertEmbed(length, "image", res.data);
        // 调整光标到最后
        quill.setSelection(length + 1);
      } else {
        this.$message.error("图片插入失败");
      }
    },
    handleUploadError() {
      this.$message.error("图片插入失败");
    },
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0
}

.editor,
.ql-toolbar {
  white-space: pre-wrap !important;
  line-height: normal !important;
}

.ql-editor {
  font-size: 16px;
  letter-spacing: 0.544px;
  line-height: 1.8;
}

.quill-img {
  display: none;
}

.ql-snow .ql-tooltip[data-mode="link"]::before {
  content: "请输入链接地址:";
}

.ql-tooltip.ql-editing {
  left: 0 !important;
}

.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: "保存";
  padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode="video"]::before {
  content: "请输入视频地址:";
}


.ql-snow .ql-picker.ql-block {
  width: 98px;
}

.ql-snow .ql-picker.ql-block .ql-picker-label[data-value="1px"]::before,
.ql-snow .ql-picker.ql-block .ql-picker-item[data-value="1px"]::before {
  content: "间距1px";
}

.ql-block-1px {
  font-size: 1px;
}

.ql-snow .ql-picker.ql-block .ql-picker-label::before,
.ql-snow .ql-picker.ql-block .ql-picker-item::before {
  content: "间距2px";
}

.ql-block-2px {
  font-size: 2px;
}

.ql-snow .ql-picker.ql-block .ql-picker-label[data-value="3px"]::before,
.ql-snow .ql-picker.ql-block .ql-picker-item[data-value="3px"]::before {
  content: "间距3px";
}

.ql-block-3px {
  font-size: 3px;
}

.ql-snow .ql-picker.ql-block .ql-picker-label[data-value="4px"]::before,
.ql-snow .ql-picker.ql-block .ql-picker-item[data-value="4px"]::before {
  content: "间距4px";
}

.ql-block-4px {
  font-size: 4px;
}

.ql-snow .ql-picker.ql-block .ql-picker-label[data-value="5px"]::before,
.ql-snow .ql-picker.ql-block .ql-picker-item[data-value="5px"]::before {
  content: "间距5px";
}

.ql-block-5px {
  font-size: 5px;
}


.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="10px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="10px"]::before {
  content: "10px";
}

.ql-size-10px {
  font-size: 10px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "16px";
}

.ql-size-16px {
  font-size: 16px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
  content: "18px";
}

.ql-size-18px {
  font-size: 18px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {
  content: "32px";
}

.ql-size-32px {
  font-size: 32px;
}


.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "文本";
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "标题1";
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "标题2";
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "标题3";
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "标题4";
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "标题5";
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "标题6";
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "标准字体";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "衬线字体";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "等宽字体";
}
</style>
